package riotutil

import (
	"encoding/json"
	"reflect"
	"strings"

	Log "github.com/cihub/seelog"
	"github.com/go-ego/riot"
	"github.com/go-ego/riot/types"
)

type RiotUtil struct{}

// 添加
func (ru RiotUtil) Add(dbName, key, data string) (bool, string, interface{}) {
	if strings.TrimSpace(dbName) == "" {
		return false, "未指定搜索库", 1001
	}

	if strings.TrimSpace(key) == "" {
		return false, "关键字为空", 1002
	}

	dbName = strings.TrimSpace(dbName)
	key = strings.TrimSpace(key)

	searcher := riot.Engine{}
	searcher.Init(types.EngineOpts{
		Using:    3,
		GseDict:  "zh",
		UseStore: true,
		//GsGseDict: "./dictionary.txt",
		//GsGseDict:       "./temp/test_dict.txt",
		//StopTokenFile: "./temp/stop_tokens.txt",
		StoreFolder: "./temp/riot/" + dbName, //存储库
	})

	defer searcher.Close()

	searcher.Index(key, types.DocData{Content: data}, true)

	searcher.Flush() //等待索引刷新完毕

	return false, "添加内容成功", key
}

// 添加
func (ru RiotUtil) Adds(dbName string, data map[string]string) (bool, string, interface{}) {
	if strings.TrimSpace(dbName) == "" {
		return false, "未指定搜索库", 1001
	}

	if len(data) < 1 {
		return false, "内容为空", 1002
	}

	dbName = strings.TrimSpace(dbName)

	searcher := riot.Engine{}
	searcher.Init(types.EngineOpts{
		Using:    3,
		GseDict:  "zh",
		UseStore: true,
		//GsGseDict: "./dictionary.txt",
		//GsGseDict:       "./temp/test_dict.txt",
		//StopTokenFile: "./temp/stop_tokens.txt",
		StoreFolder: "./temp/riot/" + dbName, //存储库
	})

	defer searcher.Close()

	for key, val := range data {
		key = strings.TrimSpace(key)
		if key == "" {
			continue
		}

		searcher.Index(key, types.DocData{Content: val}, true)
	}

	searcher.Flush() //等待索引刷新完毕

	return true, "添加内容成功", data
}

// 删除
func (ru RiotUtil) Del(dbName, key string) (bool, string, interface{}) {
	if strings.TrimSpace(dbName) == "" {
		return false, "未指定搜索库", 1001
	}

	if strings.TrimSpace(key) == "" {
		return false, "关键字为空", 1002
	}

	dbName = strings.TrimSpace(dbName)
	key = strings.TrimSpace(key)

	searcher := riot.Engine{}
	searcher.Init(types.EngineOpts{
		Using:    3,
		GseDict:  "zh",
		UseStore: true,
		//GsGseDict: "./dictionary.txt",
		//GsGseDict:       "./temp/test_dict.txt",
		//StopTokenFile: "./temp/stop_tokens.txt",
		StoreFolder: "./temp/riot/" + dbName, //存储库
	})

	defer searcher.Close()

	searcher.RemoveDoc(key, true)

	searcher.Flush() //等待索引刷新完毕

	return true, "删除内容成功", key
}

// 搜索
func (ru RiotUtil) Find(dbName, key string, entity interface{}) (bool, string, interface{}) {
	if strings.TrimSpace(dbName) == "" {
		return false, "未指定搜索库", 1001
	}

	if strings.TrimSpace(key) == "" {
		return false, "关键字为空", 1002
	}

	dbName = strings.TrimSpace(dbName)
	key = strings.TrimSpace(key)

	searcher := riot.Engine{}
	searcher.Init(types.EngineOpts{
		Using:    3,
		GseDict:  "zh",
		UseStore: true,
		//GsGseDict: "./dictionary.txt",
		//GsGseDict:       "./temp/test_dict.txt",
		//StopTokenFile: "./temp/stop_tokens.txt",
		StoreFolder: "./temp/riot/" + dbName, //存储库
	})

	defer searcher.Close()
	searcher.Flush() //等待索引刷新完毕

	res := searcher.Search(types.SearchReq{Text: key})

	if res.NumDocs < 1 {
		return false, "搜索结束,没有发现数据", 1003
	}

	if entity == nil {
		result := []string{}
		for _, val := range res.Docs.(types.ScoredDocs) {
			result = append(result, val.Content)
		}

		return true, "搜索结束", result
	}

	result := []interface{}{}
	for _, val := range res.Docs.(types.ScoredDocs) {
		bl, _, obj := ru.toObj(val.Content, entity)
		if bl {
			result = append(result, obj)
		}
	}

	return true, "搜索结束", result
}

// 内容转换到结构实体
func (ru RiotUtil) toObj(str string, entity interface{}) (bool, string, interface{}) {
	if entity == nil {
		entity = map[string]interface{}{}
	}

	str = strings.TrimSpace(str)
	if str == "" {
		return false, "没有数据", 1003
	}

	rve := reflect.New(reflect.TypeOf(entity)).Elem()
	result := rve.Interface()

	err := json.Unmarshal([]byte(str), &result)
	if err != nil {
		Log.Error("Json字符串转换异常: %+v\n", err)
		return false, "字符串转换异常", 1004
	}

	if (!strings.Contains(reflect.TypeOf(result).String(), "map[string]interface")) && (!strings.Contains(reflect.TypeOf(entity).String(), "map[string]interface")) {
		return true, "转换结束", result
	}

	//--如果转换发生错误则进行再次转换--//
	// var vMap map[string]interface{}
	vMap := result.(map[string]interface{})
	for key, val := range vMap {
		field := rve.FieldByName(key)
		if !field.IsValid() {
			continue
		}

		if (field.Type().String() == "int64") && (reflect.TypeOf(val).String() == "float64") {
			field.Set(reflect.ValueOf(int64(val.(float64))))
			continue
		}

		field.Set(reflect.ValueOf(val))
	}

	return true, "转换结束", rve.Interface()
}
